#include "Thread.hpp"



System::Thread::Thread()
{
	
}



System::Thread::~Thread()
{
	
}



void System::Thread::exec() throw(ThreadException)
{
	// Si la mutex n'est pas déjà bloquée,
	// alors elle est bloquée et on démarre le thread
	if(_started.tryLock())
	{
		int res = pthread_create(&_thread, NULL, startRoutine, this);
		
		if(res != 0)
		{
			_started.unlock();
			throw ThreadException(strerror(res));
		}
		
		pthread_join(_thread, NULL);
	}
	else
	{
		throw ThreadException("Unable to start the thread : thread already started");
	}
}



void System::Thread::start() throw(ThreadException)
{
	// Si la mutex n'est pas déjà bloquée,
	// alors elle est bloquée et on démarre le thread
	if(_started.tryLock())
	{
		pthread_attr_t attr;
		int res;
		
		pthread_attr_init(&attr);
		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
		res = pthread_create(&_thread, &attr, startRoutine, (void*)this);
		pthread_attr_destroy(&attr);
		
		if(res != 0)
		{
			_started.unlock();
			throw ThreadException(strerror(res));
		}
	}
	else
	{
		throw ThreadException("Unable to start the thread : thread already started");
	}
}



void System::Thread::wait()
{
	_started.lock();
	_started.unlock();
}



bool System::Thread::isRunning()
{
	// Si la mutex n'est pas déjà bloquée, 
	// alors elle est bloquée. Le thread n'est donc pas lancé.
	if(_started.tryLock())
	{
		// On débloque immédiatement la mutex
		_started.unlock();
		return false;
	}
	
	return true;
}



void System::Thread::sleep(double secondes)
{
    struct timeval tv;
    tv.tv_sec = (int)(secondes);
    tv.tv_usec = (int)((secondes - (double)tv.tv_sec) * 1000000);
    select(0, NULL, NULL, NULL, &tv);
}



void* System::Thread::startRoutine(void* thread)
{
	System::Thread* thisThread = (System::Thread*)thread;
	Mutex started(thisThread->_started);
	
	thisThread->run();
	started.unlock();
	
	return NULL;
}



bool System::Thread::operator==(const System::Thread& other) const
{
	if(pthread_equal(_thread, other._thread) != 0)
		return true;
	
	return false;
}




